/*
 * Copyright 2009-2010 the original author or authors.
 *
 * Licensed under the Apache license, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.internna.iwebjtracker.model;

import java.util.Locale;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.MappedSuperclass;
import javax.persistence.Transient;
import org.directwebremoting.annotations.RemoteProperty;
import org.hibernate.validator.NotEmpty;
import org.hibernate.validator.Valid;
import org.internna.iwebjtracker.project.model.Module;
import org.internna.iwebjtracker.project.model.Project;
import org.internna.iwebjtracker.project.model.Project.ProjectType;
import org.internna.iwebjtracker.project.model.Version;
import org.internna.iwebmvc.metadata.ui.EntityFilter;
import org.internna.iwebmvc.metadata.ui.EntityFilter.WIDGET_TYPE;
import org.internna.iwebmvc.metadata.ui.FormField;
import org.internna.iwebmvc.metadata.ui.GridColumn;
import org.internna.iwebmvc.model.AbstractOwnedDomainEntity;
import org.internna.iwebmvc.model.Document;

import static org.internna.iwebmvc.utils.StringUtils.hasText;

/**
 * Basic data holder for project data. This is a project implementation valid
 * for Maven2 or Free From project types.
 *
 * @author Jose Noheda
 * @since 1.0
 */
@MappedSuperclass
public abstract class ProjectDataHolder<M extends Module<P, M>, V extends Version<TrackerUser, P, V>, P extends Project<DefaultConnectionDetails, M, V, TrackerUser, P>> extends AbstractOwnedDomainEntity implements Project<DefaultConnectionDetails, M, V, TrackerUser, P> {

    private static final long serialVersionUID = 1222215027641146317L;

    /**
     * Sets default value for open.
     */
    public ProjectDataHolder() {
        this.open = true;
    }

    @Transient
    @RemoteProperty
    private ProjectType projectType;

    @Valid
    @RemoteProperty
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "CONNECTION_DETAILS")
    private DefaultConnectionDetails connectionDetails;

    @NotEmpty
    @RemoteProperty
    @GridColumn(order = 2, relativeWidth = 0.95)
    @Column(name = "PRJALIAS", nullable = false, unique = true)
    private String alias;

    @Lob
    @NotEmpty
    @RemoteProperty
    @GridColumn(order = 4)
    @Column(name = "DESCRIPTION")
    private String description;

    @RemoteProperty
    @Column(name = "RELATIVE_PATH")
    private String relativePath;

    @NotEmpty
    @RemoteProperty
    @GridColumn(order = 3, relativeWidth = 0.85)
    @Column(name = "SERVER_TYPE")
    private String serverType;

    @NotEmpty
    @EntityFilter
    @RemoteProperty
    @GridColumn(order = 1)
    @Column(name = "NAME")
    private String projectName;

    @NotEmpty
    @RemoteProperty
    @GridColumn(order = 4)
    @Column(name = "HOME")
    private String homePage;

    @JoinColumn(name = "LOGO")
    @FormField(order = 6, type = WIDGET_TYPE.DOCUMENT)
    @ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.MERGE, CascadeType.REMOVE})
    private Document logo;

    @RemoteProperty
    @GridColumn(order = 0, relativeWidth = 0.35)
    @Column(name = "ISOPEN")
    private boolean open;

    /**
     * A one word uppercase unique identifier of the project.
     *
     * @return a not empty string
     */
    public String getAlias() {
        return alias;
    }

    /**
     * Parses the provided string to convert it into a one word of capital letters. Otherwise
     * leaves the alias untouched.
     *
     * @param alias any
     */
    @Override public void setAlias(String alias) {
        this.alias = hasText(alias) ? alias.trim().toUpperCase(Locale.ENGLISH) : null;
        if (hasText(this.alias)){
            int position = this.alias.indexOf(" ");
            if (position > 0) {
                this.alias = this.alias.substring(0, position);
            }
        }
    }

    /**
     * Accessor method
     */
    public String getDescription() {
        return description;
    }

    /**
     * Accessor method
     */
    @Override public void setDescription(String description) {
        this.description = description;
    }

    /**
     * Accessor method
     */
    @Override public DefaultConnectionDetails getConnectionDetails() {
        return connectionDetails;
    }

    /**
     * Accessor method
     */
    @Override public void setConnectionDetails(DefaultConnectionDetails details) {
        connectionDetails = details;
    }

    /**
     * Accessor method
     */
    public String getRelativePath() {
        return relativePath;
    }

    /**
     * Accessor method
     */
    public void setRelativePath(String relativePath) {
        this.relativePath = relativePath;
    }

    /**
     * Accessor method
     */
    public void setServerType(String serverType) {
        this.serverType = serverType;
    }

    /**
     * Accessor method
     */
    @Override public String getServerType() {
        return serverType;
    }

    /**
     * Delegates to getProjectName()
     */
    @Override public String getCaption(Locale locale) {
        return getProjectName();
    }

    /**
     * Delegates to getRelativePath()
     */
    @Override public String getRootPath() {
        return getRelativePath();
    }

    /**
     * Obtains the complete URL to reach this project item in the server. For example,
     * http://code.google.com/p/xxx/trunk/MyProject.
     *
     * @return null if no connection details exist and the full URL otherwise.
     */
    @RemoteProperty
    @Override public String getSourceControlURL() {
        String url = connectionDetails != null ? connectionDetails.getUrl() : null;
        return hasText(url) ? url + getRelativePath() : null;
    }

    /**
     * Accessor method
     */
    @Override public ProjectType getProjectType() {
        return projectType;
    }

    /**
     * Accessor method
     */
    public void setProjectType(ProjectType projectType) {
        this.projectType = projectType;
    }

    /**
     * Retrieves the project log image showed on the main project page (top-left).
     *
     * @return null unless a logo has been added previously using the project options
     */
    public Document getLogo() {
        return logo;
    }

    /**
     * Accessor method
     */
    public void setLogo(Document logo) {
        this.logo = logo;
    }

    /**
     * Accessor method
     */
    @Override public String getHomePage() {
        return homePage;
    }

    /**
     * Accessor method
     */
    @Override public void setHomePage(String homePage) {
        this.homePage = homePage;
    }

    /**
     * Accessor method
     */
    @Override public String getProjectName() {
        return projectName;
    }

    /**
     * Establishes the project name and in turn changes the alias.
     */
    @Override public void setProjectName(String name) {
        this.projectName = name;
        if (hasText(name) && (!hasText(alias))) {
            setAlias(name);
        }
    }

    /**
     * Accessor method.
     *
     */
    public boolean isOpen() {
        return open;
    }

    /**
     * Accessor method.
     *
     * @param open any
     */
    public void setOpen(boolean open) {
        this.open = open;
    }

}
